package database

import (
	"strings"
)

const (
	flagReadOnly = 1 << iota
	flagSpecial  // command invoked in Exec
	flagWrite
	flagExpire
	flagNull
)

var cmdTable = make(map[string]*command)

type command struct {
	name string

	executor ExecFunc

	prepare PreFunc

	undo UndoFunc

	// arity 参数个数，正数表示确切数量，负数表示至少多少个
	arity int
	flags int
}

func registerCommand(name string, executor ExecFunc, prepare PreFunc, rollback UndoFunc, arity int, flags int) *command {
	name = strings.ToLower(name)
	cmd := &command{
		name:     name,
		executor: executor,
		prepare:  prepare,
		undo:     rollback,
		arity:    arity,
		flags:    flags,
	}
	cmdTable[name] = cmd
	return cmd
}

func registerSpecialCommand(name string, arity int, flags int) *command {
	name = strings.ToLower(name)
	flags |= flagSpecial
	cmd := &command{
		name:  name,
		arity: arity,
		flags: flags,
	}
	cmdTable[name] = cmd
	return cmd
}

func getCmd(key string) *command {
	cmd, ok := cmdTable[strings.ToLower(key)]
	if !ok {
		return nil
	}
	return cmd
}

func (cmd *command) IsWriter() bool {
	return cmd.flags&flagWrite != 0
}

func (cmd *command) AboutExpire() bool {
	return cmd.flags&flagExpire != 0
}
